package com.liruo.enumconverter.core.jackson;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.liruo.enumconverter.core.converter.SourceEnumGenericConverter;
import com.liruo.enumconverter.model.SourceEnum;

import java.io.IOException;

public class SourceEnumJackDeserializer extends JsonDeserializer<SourceEnum<?>> implements ContextualDeserializer {
    private final SourceEnumGenericConverter sourceEnumGenericConverter;
    private final Class<?> enumClazz;
    public SourceEnumJackDeserializer(SourceEnumGenericConverter sourceEnumGenericConverter) {
        this.sourceEnumGenericConverter = sourceEnumGenericConverter;
        this.enumClazz = null;
    }

    public SourceEnumJackDeserializer(SourceEnumGenericConverter sourceEnumGenericConverter, Class<?> enumClazz) {
        if(!sourceEnumGenericConverter.isSourceEnum(enumClazz)){
            throw new IllegalArgumentException(enumClazz.getName() + " is not a legal SourceEnum, require source is Integer or String");
        }
        this.sourceEnumGenericConverter = sourceEnumGenericConverter;
        this.enumClazz = enumClazz;
    }

    @Override
    public SourceEnum<?> deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException, JacksonException {
        JsonToken jsonToken = jsonParser.currentToken();
        Object source = null;
        if(jsonToken == JsonToken.VALUE_STRING){
            source = jsonParser.getText();
        }else if(jsonToken == JsonToken.VALUE_NUMBER_INT){
            source = jsonParser.getIntValue();
        }
        return source == null ? null :
                sourceEnumGenericConverter.deserialize(source, (Class<? extends SourceEnum<?>>)this.enumClazz);
    }

    /**
     * 在注册时，确保rawClass是SourceEnum的子类
     */
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException {
        Class<?> rawClass = deserializationContext.getContextualType().getRawClass();
        if(!SourceEnum.class.isAssignableFrom(rawClass)){
            return null;
        }
        return new SourceEnumJackDeserializer(this.sourceEnumGenericConverter,
                rawClass);
    }
}